//+------------------------------------------------------------------+
//|                                                         6666.mq5 |
//|                                  Copyright 2025, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"

// 输入参数
input ulong      InpMagicNumber = 123456;     // EA魔术编号
input string     InpNoTradeTimeStart = "19:30"; // 不交易时间段开始(服务器时间)
input string     InpNoTradeTimeEnd = "23:30";   // 不交易时间段结束(服务器时间)
input double     InpProfitMultiplier = 2.0;   // 盈利乘数(用于计算平仓目标)
input int        InpMAPeriod1 = 5;            // 均线1周期
input int        InpMAPeriod2 = 10;           // 均线2周期
input int        InpMAPeriod3 = 15;           // 均线3周期
input int        InpMAPeriod4 = 20;           // 均线4周期
input int        InpMAPeriod5 = 25;           // 均线5周期
input int        InpMAPeriod6 = 30;           // 均线6周期
input ENUM_APPLIED_PRICE InpMAAppliedPrice = PRICE_CLOSE; // 均线应用价格
input ENUM_MA_METHOD InpMAMethod = MODE_SMA;  // 均线计算方法
input int        InpGridStep = 300;           // 网格间距(点)
input double     InpLotSize1 = 0.01;          // 加仓手数1
input double     InpLotSize2 = 0.01;          // 加仓手数2
input double     InpLotSize3 = 0.03;          // 加仓手数3
input double     InpLotSize4 = 0.05;          // 加仓手数4
input double     InpLotSize5 = 0.10;          // 加仓手数5
input double     InpLotSize6 = 0.18;          // 加仓手数6
input double     InpLotSize7 = 0.34;          // 加仓手数7
input double     InpLotSize8 = 0.61;          // 加仓手数8
input double     InpLotSize9 = 1.10;          // 加仓手数9
input double     InpLotSize10 = 1.98;         // 加仓手数10
input double     InpLotSize11 = 3.57;         // 加仓手数11
input double     InpLotSize12 = 0.64;         // 加仓手数12
input double     InpLotSize13 = 1.10;         // 加仓手数13
input double     InpLotSize14 = 3.30;         // 加仓手数14
input double     InpLotSize15 = 4.30;         // 加仓手数15

// 全局变量
int maHandles[6];        // 均线指标句柄数组
double maValues[6];      // 均线值数组
datetime lastBarTime = 0;// 最后处理的K线时间
bool filterEnabled = false; // 持仓过滤开关状态
long chartID = 0;       // 图表ID
int buttonId = 1;       // 按钮ID
int flage = -1;         // 多空标志
double lastOrderPrice = 0; // 最后订单价格
int orderCount = 0;     // 订单计数
double lotSizes[15];    // 加仓手数数组

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   // 初始化加仓手数数组
   lotSizes[0] = InpLotSize1;
   lotSizes[1] = InpLotSize2;
   lotSizes[2] = InpLotSize3;
   lotSizes[3] = InpLotSize4;
   lotSizes[4] = InpLotSize5;
   lotSizes[5] = InpLotSize6;
   lotSizes[6] = InpLotSize7;
   lotSizes[7] = InpLotSize8;
   lotSizes[8] = InpLotSize9;
   lotSizes[9] = InpLotSize10;
   lotSizes[10] = InpLotSize11;
   lotSizes[11] = InpLotSize12;
   lotSizes[12] = InpLotSize13;
   lotSizes[13] = InpLotSize14;
   lotSizes[14] = InpLotSize15;
   
   // 打印当前品种、周期和魔术编号
   Print("EA初始化 - 魔术编号: ", InpMagicNumber);
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   Print("EA已卸载，魔术编号: ", InpMagicNumber);
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   flage=1;
   // 调用马丁网格交易函数
   MartinGridTrading();
}

//+------------------------------------------------------------------+
//| 检查并恢复状态                                                   |
//+------------------------------------------------------------------+
void CheckAndRestoreState()
{
   int total = PositionsTotal();
   if(total == 0) 
   {
      Print("没有持仓，退出恢复状态检查");
      return;
   }
   
   // 统计当前品种的多空持仓
   int buyPositions = 0;
   int sellPositions = 0;
   double buyVolume = 0;
   double sellVolume = 0;
   double lowestBuyPrice = DBL_MAX;
   double highestSellPrice = 0;
   
   for(int i = 0; i < total; i++)
   {
      ulong ticket = PositionGetTicket(i);
      if(PositionSelectByTicket(ticket))
      {
         string symbol = PositionGetString(POSITION_SYMBOL);
         if(symbol == _Symbol) // 只检查当前品种
         {
            long type = PositionGetInteger(POSITION_TYPE);
            double volume = PositionGetDouble(POSITION_VOLUME);
            double price = PositionGetDouble(POSITION_PRICE_OPEN);
            
            if(type == POSITION_TYPE_BUY)
            {
               buyPositions++;
               buyVolume += volume;
               if(price < lowestBuyPrice) lowestBuyPrice = price;
            }
            else if(type == POSITION_TYPE_SELL)
            {
               sellPositions++;
               sellVolume += volume;
               if(price > highestSellPrice) highestSellPrice = price;
            }
         }
      }
   }
   
   // 确定主要方向
   if(buyPositions > 0 && sellPositions > 0)
   {
      Print("发现双向持仓，无法恢复状态");
      return;
   }
   else if(buyPositions > 0)
   {
      flage = 1;
      lastOrderPrice = lowestBuyPrice;
      orderCount = EstimateOrderCount(buyVolume);
      Print("恢复多头状态 - 最后开仓价: ", lastOrderPrice, " 订单计数: ", orderCount, " 总手数: ", buyVolume);
   }
   else if(sellPositions > 0)
   {
      flage = 0;
      lastOrderPrice = highestSellPrice;
      orderCount = EstimateOrderCount(sellVolume);
      Print("恢复空头状态 - 最后开仓价: ", lastOrderPrice, " 订单计数: ", orderCount, " 总手数: ", sellVolume);
   }
}

//+------------------------------------------------------------------+
//| 估算订单数量                                                     |
//+------------------------------------------------------------------+
int EstimateOrderCount(double totalVolume)
{
   double cumulativeVolume = 0;
   for(int i = 0; i < ArraySize(lotSizes); i++)
   {
      cumulativeVolume += lotSizes[i];
      if(totalVolume <= cumulativeVolume + 0.0001) // 考虑浮点精度
      {
         return i + 1;
      }
   }
   return ArraySize(lotSizes);
}

//+------------------------------------------------------------------+
//| 马丁网格交易函数                                                 |
//+------------------------------------------------------------------+
void MartinGridTrading()
{
   // 检查并恢复状态
   CheckAndRestoreState();
   
   // 检查标志位
   if(flage == -1) return;  // 只有当方向未确定时才返回
   
   // 获取当前价格
   double currentPrice = SymbolInfoDouble(_Symbol, flage == 1 ? SYMBOL_ASK : SYMBOL_BID);
   
   // 如果没有订单，开初始仓
   if(PositionsTotal() == 0)
   {
      OpenInitialPosition(currentPrice);
      return;
   }
   
   // 检查是否需要加仓
   CheckForAddingPosition(currentPrice);
}

//+------------------------------------------------------------------+
//| 开初始仓位                                                       |
//+------------------------------------------------------------------+
void OpenInitialPosition(double price)
{
   // 重置订单计数和最后订单价格
   orderCount = 0;
   lastOrderPrice = price;
   
   // 计算手数
   double lotSize = lotSizes[0];
   
   // 开仓
   MqlTradeRequest request = {};
   MqlTradeResult result = {};
   
   request.action = TRADE_ACTION_DEAL;
   request.symbol = _Symbol;
   request.volume = lotSize;
   request.type = (flage == 1) ? ORDER_TYPE_BUY : ORDER_TYPE_SELL;
   request.price = price;
   request.deviation = 10;
   request.magic = InpMagicNumber;
   request.comment = "Initial position";
   
   if(!OrderSend(request, result))
   {
      Print("开初始仓位失败, 错误码: ", GetLastError());
      return;
   }
   
   Print("初始仓位已开: ", EnumToString(request.type), " 价格: ", price, " 手数: ", lotSize);
   orderCount++;
}

//+------------------------------------------------------------------+
//| 检查是否需要加仓                                                 |
//+------------------------------------------------------------------+
void CheckForAddingPosition(double currentPrice)
{
   // 计算价格差(点)
   int priceDiff = (int)((currentPrice - lastOrderPrice) / _Point * (flage == 1 ? -1 : 1));
   
   // 如果亏损达到网格间距
   if(priceDiff >= InpGridStep)
   {
      // 计算需要加仓的次数
      int steps = priceDiff / InpGridStep;
      
      // 确保不超过手数数组大小
      if(orderCount + steps > ArraySize(lotSizes))
      {
         steps = ArraySize(lotSizes) - orderCount;
         if(steps <= 0) return;
      }
      
      // 加仓
      for(int i = 0; i < steps; i++)
      {
         AddPosition(currentPrice);
      }
   }
}

//+------------------------------------------------------------------+
//| 加仓                                                             |
//+------------------------------------------------------------------+
void AddPosition(double price)
{
   // 确保不超过手数数组大小
   if(orderCount >= ArraySize(lotSizes)) return;
   
   // 计算手数
   double lotSize = lotSizes[orderCount];
   
   // 开仓
   MqlTradeRequest request = {};
   MqlTradeResult result = {};
   
   request.action = TRADE_ACTION_DEAL;
   request.symbol = _Symbol;
   request.volume = lotSize;
   request.type = (flage == 1) ? ORDER_TYPE_BUY : ORDER_TYPE_SELL;
   request.price = price;
   request.deviation = 10;
   request.magic = InpMagicNumber;
   request.comment = "Add position #" + IntegerToString(orderCount + 1);
   
   if(!OrderSend(request, result))
   {
      Print("加仓失败, 错误码: ", GetLastError());
      return;
   }
   
   Print("加仓 #", orderCount + 1, ": ", EnumToString(request.type), " 价格: ", price, " 手数: ", lotSize);
   lastOrderPrice = price;
   orderCount++;
}